package ink.xiaobaibai.service.monthly.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import ink.xiaobaibai.bo.BindOneMonthlyOrder;
import ink.xiaobaibai.common.MyRole;
import ink.xiaobaibai.common.ServiceResult;
import ink.xiaobaibai.entity.*;
import ink.xiaobaibai.enumOxy.DepositStatus;
import ink.xiaobaibai.enumOxy.MonthlyDeviceStatus;
import ink.xiaobaibai.enumOxy.MonthlyfeeOrderStatus;
import ink.xiaobaibai.service.*;
import ink.xiaobaibai.service.monthly.IOrderProcedureService;
import ink.xiaobaibai.serviceOxy.ISmsService;
import ink.xiaobaibai.serviceOxy.monthly.IDelayMonControlService;
import ink.xiaobaibai.serviceOxy.pay.IPayService;
import ink.xiaobaibai.units.MySecurity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

/**
 * @description: 包月订单流程
 * @author: 小白白
 * @create: 2021-05-31
 **/

@Service
@Slf4j
public class OrderProcedureServiceImpl implements IOrderProcedureService {

    @Autowired
    private IMonthlyfeeDeviceService deviceService;

    @Autowired
    private IMonthlyfeeOrderService orderService;

    @Autowired
    private ILogisticsService logisticsService;

    @Autowired
    private IMonthlyUserDeviceService userDeviceService;

    @Autowired
    private OrderProcedureServiceImpl orderProcedureServiceImpl;

    @Autowired
    private IMonthlyfeeDepositService depositService;

    @Autowired
    private IDelayMonControlService delayMonService;

    @Autowired
    private IMonthlyRefundDepositService refundDepositService;

    @Autowired
    private IMonthlyfeeOrderService monthlyfeeOrderService;

    @Autowired
    private ISmsService smsService;

    @Autowired
    private IAdminUserService adminUserService;

    @Autowired
    private IPayService payService;

    /**
     * 业务员绑定待 未分配 状态订单
     */
    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ServiceResult bindOneAdd(BindOneMonthlyOrder bindOneMonthlyOrder) {
        Integer userId = MySecurity.getUserId();
        String orderId = bindOneMonthlyOrder.getOrderId();
        //权限(人人都是可以分配机器)
//        String role = MySecurity.getRole();
//        if(!role.equals(MyRole.DISTRIBUTOR)){
//            return ServiceResult.fail("非业务员不可操作");
//        }
        QueryWrapper<MonthlyfeeOrder> q0 = new QueryWrapper<>();
        q0.select("status", "admin_user_id", "user_id", "logistics_id");
        q0.eq("order_id", orderId);
        MonthlyfeeOrder monthlyfeeOrder = this.orderService.getOne(q0);

        //月费管理+管理员可以操作
        if (!MySecurity.isPower(MyRole.POWER_MONTHLY) && !monthlyfeeOrder.getAdminUserId().equals(userId)) {
            return ServiceResult.fail("无权限操作他人订单");
        }
        //状态
        if (!monthlyfeeOrder.getStatus().equals(MonthlyfeeOrderStatus.UNALLOCATED.getStatus())) {
            return ServiceResult.fail("当前已分配机器,当前状态:" + monthlyfeeOrder.getStatus());
        }
        //本人机器 与 机器状态
        Integer deviceId = bindOneMonthlyOrder.getDeviceId();
        //内部会修改机器状态
        ServiceResult serviceResult = this.orderProcedureServiceImpl.baseOneValidDeviceByUser(userId, deviceId, this.deviceService);
        if (!serviceResult.isOk()) {
            return serviceResult;
        }
        UpdateWrapper<Logistics> u0 = new UpdateWrapper<>();
        u0.set("images_uri", bindOneMonthlyOrder.getImageUrl());
        u0.set("send_cost", bindOneMonthlyOrder.getSendCost());
        u0.set("number", bindOneMonthlyOrder.getNumber());
        u0.eq("id", monthlyfeeOrder.getLogisticsId());
        this.logisticsService.update(u0);

        //修改状态
        UpdateWrapper<MonthlyfeeOrder> u1 = new UpdateWrapper<>();
        u1.set("trial_day", bindOneMonthlyOrder.getTrialDay());
        u1.set("extended_day", bindOneMonthlyOrder.getExtendedDay());
        u1.set("device_id", bindOneMonthlyOrder.getDeviceId());
        u1.set("logistics_id", monthlyfeeOrder.getLogisticsId());
        boolean isAdmin = false;
        if (MySecurity.isPower(MyRole.POWER_MONTHLY)) {
            //直接去进行激活
            isAdmin = true;
        } else if (MySecurity.getRole().equals(MyRole.AGENT)) {
            u1.set("status", MonthlyfeeOrderStatus.ADMIN.getStatus());
            this.smsService.oaSms(1, "月费机器审核");
        } else {
            u1.set("status", MonthlyfeeOrderStatus.AGENT.getStatus());
            this.smsService.oaSms(this.adminUserService.getAgentIdByDepId(this.adminUserService.getDepId(MySecurity.getUserId())).getId(), "月费机器审核");
        }
        u1.eq("order_id", orderId);
        u1.eq("status", MonthlyfeeOrderStatus.UNALLOCATED.getStatus());
        //修改式保存
        if (!this.orderService.update(u1)) {
            throw new RuntimeException("未知原因,绑定失败");
        }

        //用户-机器映射
        MonthlyUserDevice userDevice = new MonthlyUserDevice(monthlyfeeOrder.getUserId(), deviceId, false);
        this.userDeviceService.save(userDevice);
        //押金绑定机器id
        QueryWrapper<MonthlyfeeDeposit> q2 = new QueryWrapper<>();
        q2.select("order_id");
        q2.eq("user_id", monthlyfeeOrder.getUserId());
        q2.eq("status", DepositStatus.OCCUPIED.getStatus());
        q2.eq("device_id", -1);
        q2.last("limit 1");
        MonthlyfeeDeposit deposit = this.depositService.getOne(q2);
        deposit.setDeviceId(deviceId);
        this.depositService.updateById(deposit);
        if (isAdmin) {
            // 进行激活
            this.binThree(orderId);
        }
        return ServiceResult.ok();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public ServiceResult binOneUpdate(BindOneMonthlyOrder bindOneMonthlyOrder) {

        /**
         * 未激活状态才可以修改
         * 可修改: 试用天数,延长天数,对应机器id,物流信息
         */
        Integer userId = MySecurity.getUserId();
        //权限
//        String role = MySecurity.getRole();
//        if(!role.equals(MyRole.DISTRIBUTOR)){
//            return ServiceResult.fail("非业务员不可操作");
//        }
        //总对象
        String orderId = bindOneMonthlyOrder.getOrderId();
        MonthlyfeeOrder monthlyfeeOrder = this.orderService.getById(orderId);
        //权限
        if (!MySecurity.isPower(MyRole.POWER_MONTHLY) && !monthlyfeeOrder.getAdminUserId().equals(userId)) {
            return ServiceResult.fail("无权限操作他人订单");
        }
        //状态
        if (monthlyfeeOrder.getStatus().equals(MonthlyfeeOrderStatus.INUSE.getStatus())) {
            return ServiceResult.fail("用户已激活,无法修改");
        }
//        if(monthlyfeeOrder.getStatus().equals(MonthlyfeeOrderStatus.ACTIVATED.getStatus())){
//            return ServiceResult.fail("管理已通过审核,无法修改");
//        }
        //修改试用天数
        if (bindOneMonthlyOrder.getTrialDay() != null) {
            monthlyfeeOrder.setTrialDay(bindOneMonthlyOrder.getTrialDay());
        }
        //修改延时天数
        if (bindOneMonthlyOrder.getExtendedDay() != null) {
            monthlyfeeOrder.setExtendedDay(bindOneMonthlyOrder.getExtendedDay());
        }
        //机器id
        if (!bindOneMonthlyOrder.getDeviceId().equals(monthlyfeeOrder.getDeviceId()) && monthlyfeeOrder.getDeviceId() != null) {
            //修改了机器
            Integer newDeviceId = bindOneMonthlyOrder.getDeviceId();
            Integer oldDeviceId = monthlyfeeOrder.getDeviceId();
            //状态修改
            monthlyfeeOrder.setDeviceId(newDeviceId);
            //本人机器 与 机器状态
            //在里面新机器已经借出了(自调用,防止事务失效)
            ServiceResult serviceResult = this.orderProcedureServiceImpl.baseOneValidDeviceByUser(userId, newDeviceId, this.deviceService);
            if (!serviceResult.isOk()) {
                return serviceResult;
            }
            //可以进行修改机器, 1.对应表 2.机器状态
            //旧机器空闲
            UpdateWrapper<MonthlyfeeDevice> u1 = new UpdateWrapper<>();
            u1.eq("id", oldDeviceId);
            u1.set("status", MonthlyDeviceStatus.FREE.getStatus());
//            u1.set("order_id","-1");
            this.deviceService.update(u1);
            //对应表修改
            UpdateWrapper<MonthlyUserDevice> u3 = new UpdateWrapper<>();
            u3.eq("user_id", monthlyfeeOrder.getUserId());
            u3.eq("device_id", oldDeviceId);
            u3.set("device_id", newDeviceId);
            this.userDeviceService.update(u3);
            //押金绑定新机器id
            QueryWrapper<MonthlyfeeDeposit> q2 = new QueryWrapper<>();
            q2.select("order_id");
            q2.eq("user_id", monthlyfeeOrder.getUserId());
            q2.eq("device_id", oldDeviceId);
            q2.last("limit 1");
            MonthlyfeeDeposit deposit = this.depositService.getOne(q2);
            deposit.setDeviceId(newDeviceId);
            this.depositService.updateById(deposit);
        }
        //物流信息
        UpdateWrapper<Logistics> u1 = new UpdateWrapper<>();
        u1.eq("id", monthlyfeeOrder.getLogisticsId());
        u1.set("images_uri", bindOneMonthlyOrder.getImageUrl());
        u1.set("send_cost", bindOneMonthlyOrder.getSendCost());
        u1.set("number", bindOneMonthlyOrder.getNumber());
        this.logisticsService.update(u1);
        //防止 经理,管理并发冲突
        monthlyfeeOrder.setStatus(null);
        //修改保存
        this.orderService.updateById(monthlyfeeOrder);
        return ServiceResult.ok();
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void binThree(String orderId) {
        //审核通过
        UpdateWrapper<MonthlyfeeOrder> u1 = new UpdateWrapper<>();
        u1.eq("order_id", orderId);
        // 直接变成使用中状态(激活状态) 去除待激活状态
        u1.set("status", MonthlyfeeOrderStatus.INUSE.getStatus());
        //改为待激活状态
        this.orderService.update(u1);
        //用户-机器状态 (case:映射并发问题)
        QueryWrapper<MonthlyfeeOrder> q1 = new QueryWrapper<>();
        q1.select("device_id", "user_id");
        q1.eq("order_id", orderId);
        MonthlyfeeOrder order = this.orderService.getOne(q1);
        UpdateWrapper<MonthlyUserDevice> u2 = new UpdateWrapper<>();
        //可用状态
        u2.set("can_use", true);
        u2.eq("user_id", order.getUserId());
        u2.eq("device_id", order.getDeviceId());
        this.userDeviceService.update(u2);
        //放入7天自动激活延时队列
//        delayMonService.autoActivation(orderId);
    }

    @Override
//    @Transactional(rollbackFor = RuntimeException.class)
    public void okDepositReturn(MonthlyfeeDeposit deposit) {
        //修改退款表 删除用户机器表 删除押金表 修改机器表 订单表
        //修改退款表
        /**
         * 此段代码放到了退款回调中
         */
//        String depositId = deposit.getOrderId();
//        UpdateWrapper<MonthlyRefundDeposit> u1=new UpdateWrapper<>();
//        u1.set("status", ReturnDepositStatus.OK.getStatus());
//        u1.eq("deposit_id",depositId);
//        refundDepositService.update(u1);
//        //删除用户机器映射
//        Integer clientUserId = deposit.getUserId();
//        Integer deviceId = deposit.getDeviceId();
//        QueryWrapper<MonthlyUserDevice> q1=new QueryWrapper<>();
//        q1.eq("user_id",clientUserId);
//        q1.eq("device_id",deviceId);
//        userDeviceService.remove(q1);
//        //删除押金表
//        depositService.removeById(depositId);
//        //修改机器表
//        UpdateWrapper<MonthlyfeeDevice> u2=new UpdateWrapper<>();
//        u2.set("status", MonthlyDeviceStatus.FREE.getStatus());
//        u2.eq("id",deposit);
//        deviceService.update(u2);
//        //修改订单表
//        UpdateWrapper<MonthlyfeeOrder> u3=new UpdateWrapper<>();
//        u3.set("status",MonthlyfeeOrderStatus.COMPLETED.getStatus());
//        u3.eq("status",MonthlyfeeOrderStatus.APDEPOSIT.getStatus());
//        u3.eq("user_id",clientUserId);
//        monthlyfeeOrderService.update(u3);
        QueryWrapper<MonthlyRefundDeposit> q1 = new QueryWrapper<>();
        q1.select("id");
        q1.eq("deposit_id", deposit.getOrderId());
        MonthlyRefundDeposit refundDeposit = this.refundDepositService.getOne(q1);
        this.payService.refundPayAmount(refundDeposit.getId());
    }

    /**
     * 验证机器与管理人,并且修改机器为正在使用inuse状态
     */
    private ServiceResult baseOneValidDeviceByUser(Integer userId, Integer deviceId, IMonthlyfeeDeviceService deviceService) {
        QueryWrapper<MonthlyfeeDevice> q1 = new QueryWrapper<>();
        q1.eq("admin_user_id", userId);
        q1.eq("id", deviceId);
        MonthlyfeeDevice device = deviceService.getOne(q1);
        if (device == null) {
            return ServiceResult.fail("对应机器不存在");
        }
        if (device.getStatus().equals(MonthlyDeviceStatus.INUSE.getStatus())) {
            return ServiceResult.fail("当前机器已借出");
        }
        if (device.getOxygenId() == null) {
            return ServiceResult.fail("当前机器未绑定氧气机");
        }
        //新机器借出
        UpdateWrapper<MonthlyfeeDevice> u2 = new UpdateWrapper<>();
        u2.eq("id", deviceId);
        u2.set("status", MonthlyDeviceStatus.INUSE.getStatus());
        deviceService.update(u2);
        return ServiceResult.ok();
    }

}
